#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glob.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <pthread.h>


#include "proto.h"
#include "media_lib.h"


struct mlib_chn_context_st
{
	chnid_t chnid;
	int chn_num;
//	char *desc;
//	mytbf_t *tbf;
	glob_t glob;
	int curr;
	int fd;
}__attribute__((packed));;


/*
struct mlib_chn_data_st
{
	chnid_t chnid;
	ssize_t	datasize;
	unint8_t data[1];
};

*/

int chn_data_init = 0;
static struct mlib_chn_context_st *chn;
static struct mlib_chn_data_st **chndata;
pthread_mutex_t path_mut = PTHREAD_MUTEX_INITIALIZER;
void free_mlib_chn_context_st();

int get_path(const char *lib_path)
{
	char curpath[200];
	glob_t globers;
	struct stat statres;
	int err, i;
	
	if (lstat(lib_path, &statres) < 0) {
		perror("lstat");
		exit(1);
	}

	if ((statres.st_mode & S_IFMT) != S_IFDIR) {
		fprintf(stderr, "Not a directory!\n");
		exit(1);
	}

	strcpy(curpath, lib_path);
	strcat(curpath, "/*");
	err = glob(curpath, 0, NULL, &globers);
	if (err) {
		fprintf(stderr, "glob() error:%d\n", err);
		exit(1);
	}

	chn = malloc(sizeof(struct mlib_chn_context_st)*globers.gl_pathc);
	chndata = malloc(sizeof(struct mlin_chn_data_st *)*globers.gl_pathc);

	if (chn == NULL)
		return -1;

	chnid_t curid;
	for (i = 0; i < globers.gl_pathc; i++) {
		if (lstat(globers.gl_pathv[i], &statres) < 0) {
			perror("lstat(pathv)");
			exit(1);
		}
		if ((statres.st_mode & S_IFMT) != S_IFDIR) {
			continue;
		}

		curid = (chnid_t)(atoi(strrchr(globers.gl_pathv[i],'/')+1)-1);
		(chn+curid)->chnid = curid;
		(chn+curid)->curr = 0;

		strcpy(curpath, globers.gl_pathv[i]);
		strcat(curpath, "/*.mp3");
		err = glob(curpath, 0, NULL, &(chn+curid)->glob);
		if (err) {
			fprintf(stderr, "glob(/*.mp3) error:%d\n", err);
			//exit(1);
		}

	}
	
	globfree(&globers);
	atexit(free_mlib_chn_context_st);

	return 0;
}

void free_mlib_chn_context_st()
{
	int i;
	for(i = 0; i < (chn+1)->chn_num; i++) {
		if((chn+i) != NULL)
			globfree(&(chn+i)->glob);
	}

	free(chn);
	free(chndata);
}


struct mlib_chn_data_st *mlib_getchndata(chnid_t chn_id)
{
	chnid_t curid = chn_id - 1;
	ssize_t data_size;

	pthread_mutex_lock(&path_mut);
	if (chn_data_init == 0) {
		if (get_path("Redio") < 0) {
			fprintf(stderr,"get_path() error!\n");
			exit(1);
		}
		chn_data_init = 1;
	}
	pthread_mutex_unlock(&path_mut);

	if ((chn+curid)->curr >= (chn+curid)->glob.gl_pathc)
		return NULL;

	struct stat statres;

//	printf("load media: %s\n",((chn+curid)->glob.gl_pathv[(chn+curid)->curr]));
	if (lstat(((chn+curid)->glob.gl_pathv[(chn+curid)->curr]), &statres) < 0) {
		perror("getchndata:lstat()");
		exit(1);
	}

	*(chndata+curid) = malloc(sizeof(struct mlib_chn_data_st) + statres.st_size - 1);

	memset(*(chndata+curid), '\0', sizeof(struct mlib_chn_data_st) + statres.st_size - 1);
	if (*(chndata+curid) == NULL)
		return NULL;

	(*(chndata+curid))->chnid = chn_id;
	(*(chndata+curid))->datasize = 0;
	data_size = statres.st_size;

	(chn+curid)->fd = open((chn+curid)->glob.gl_pathv[(chn+curid)->curr],O_RDONLY);
	if ((chn+curid)->fd < 0) {
		perror("open()");
		exit(1);
	}

	for(;;) {
		data_size =	read((chn+curid)->fd, ((*(chndata+curid))->data)+((*(chndata+curid))->datasize),\
				statres.st_size - (*(chndata+curid))->datasize);
		if (data_size <= 0) {
			if (data_size < 0) {
				perror("read()");
				exit(1);
			}
			break;
		}
		(*(chndata+curid))->datasize +=data_size;
	}
	close((chn+curid)->fd);

	++(chn+curid)->curr;
	return *(chndata+curid);
}

int mlib_freechndata(struct mlib_chn_data_st *chndata)
{
	free(chndata);
	return 0;
}
